﻿using System;
using System.Collections.Generic;

namespace State_Machine
{
    /// <summary>
    /// State machine
    /// </summary>
    public class Machine
    {
        Dictionary<string, State> states = new Dictionary<string, State>();
        State currentState = null;
        private State initialState = null;

        public Machine()
        {

        }

        /// <summary>
        /// Add a state to the machine
        /// </summary>
        /// <param name="stateName">the name of the new state</param>
        public void addState(string stateName)
        {
            states.Add(stateName, new State());
        }

        /// <summary>
        /// Set the initial state of the machine
        /// </summary>
        /// <param name="stateName">the name of the initial state</param>
        /// <returns></returns>
        public bool setInitialState(string stateName)
        {
            // You can set your machine freely, you can only set the initial state one time
            if (currentState != null)
                return false;

            if (!states.ContainsKey(stateName))
                return false;

            initialState = currentState = states[stateName];
            return true;
        }

        /// <summary>
        /// Add a transition between two state
        /// </summary>
        /// <param name="startStateName">the name of the start state</param>
        /// <param name="transitionName">the name of the transition</param>
        /// <param name="finalStateName">the name of the final state</param>
        /// <returns></returns>
        public bool addTransition(string startStateName, string transitionName, string finalStateName)
        {
            if (!states.ContainsKey(startStateName))
                return false;

            if (!states.ContainsKey(finalStateName))
                return false;

            states[startStateName].addTransition(transitionName, states[finalStateName]);
            return true;
        }

        /// <summary>
        /// Change the machine state by doing a transition
        /// </summary>
        /// <param name="transitionName">name of the transition to apply</param>
        /// <returns></returns>
        public bool doTransition(string transitionName)
        {
            if (currentState.isAble(transitionName))
            {
                currentState = currentState.getState(transitionName);
                return true;
            }
            else
                return false;
        }

        /// <summary>
        /// Get if the machine is at the start point
        /// </summary>
        /// <returns></returns>
        public bool isAtEntry()
        {
            return initialState == currentState;
        }

        /// <summary>
        /// Get if the machine is at the final point
        /// </summary>
        /// <returns></returns>
        public bool isAtExitState()
        {
            return currentState.isFinal();
        }

        /// <summary>
        /// Get if this transition is possible
        /// </summary>
        /// <param name="transitionName"></param>
        /// <returns></returns>
        public bool isAble(string transitionName)
        {
            return currentState.isAble(transitionName);
        }

        /// <summary>
        /// Get the current name of the state
        /// </summary>
        /// <returns></returns>
        public string getCurrentStateName()
        {
            foreach (string it_name in states.Keys)
            {
                if (states[it_name] == currentState)
                    return it_name;
            }
            return null;    // Not possible
        }



    }
}
